<!DOCTYPE html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/jexo/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/jexo/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/jexo/css/main.css?v=5.1.4" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/jexo/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/jexo/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/jexo/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/jexo/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Android,RxJava,源码解析," />










<meta name="description" content="Cache操作符功能介绍缓存前面操作通过onNext所传递下来的参数，在下一次subscribe订阅时，直接跳过前面的步骤，直接执行后面步骤。 用途单纯用文字介绍Cache的功能，大家可能很难理解。大家可以想象下，比如http请求，我的前面操作是有延时的，如果没有用cache，每次subscribe都会去真正发起http请求。但是如果在尾部添加cache操作符的话，那么下一次subscribe的">
<meta name="keywords" content="Android,RxJava,源码解析">
<meta property="og:type" content="article">
<meta property="og:title" content="我是用来缓存的操作符-----Cache">
<meta property="og:url" content="http://ja_project.gitee.io/jexo/2018/04/22/我是用来缓存的操作符-Cache/index.html">
<meta property="og:site_name" content="Ling Hu Blog">
<meta property="og:description" content="Cache操作符功能介绍缓存前面操作通过onNext所传递下来的参数，在下一次subscribe订阅时，直接跳过前面的步骤，直接执行后面步骤。 用途单纯用文字介绍Cache的功能，大家可能很难理解。大家可以想象下，比如http请求，我的前面操作是有延时的，如果没有用cache，每次subscribe都会去真正发起http请求。但是如果在尾部添加cache操作符的话，那么下一次subscribe的">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/4241874-570970126466b212.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/4241874-8d749caf6082f056.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/4241874-570970126466b212.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="https://upload-images.jianshu.io/upload_images/4241874-67860a5e18e7f6c7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:updated_time" content="2018-04-22T08:53:38.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="我是用来缓存的操作符-----Cache">
<meta name="twitter:description" content="Cache操作符功能介绍缓存前面操作通过onNext所传递下来的参数，在下一次subscribe订阅时，直接跳过前面的步骤，直接执行后面步骤。 用途单纯用文字介绍Cache的功能，大家可能很难理解。大家可以想象下，比如http请求，我的前面操作是有延时的，如果没有用cache，每次subscribe都会去真正发起http请求。但是如果在尾部添加cache操作符的话，那么下一次subscribe的">
<meta name="twitter:image" content="https://upload-images.jianshu.io/upload_images/4241874-570970126466b212.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/jexo/',
    scheme: 'Mist',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://ja_project.gitee.io/jexo/2018/04/22/我是用来缓存的操作符-Cache/"/>





  <title>我是用来缓存的操作符-----Cache | Ling Hu Blog</title>
  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?abc8796c232e2b898d516245257842b4";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/jexo/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Ling Hu Blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/jexo/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/jexo/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/jexo/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/jexo/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/jexo/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://ja_project.gitee.io/jexo/jexo/2018/04/22/我是用来缓存的操作符-Cache/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Ling Hu">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/jexo/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Ling Hu Blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">我是用来缓存的操作符-----Cache</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-04-22T16:49:31+08:00">
                2018-04-22
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/jexo/categories/RxJava操作符源码解析/" itemprop="url" rel="index">
                    <span itemprop="name">RxJava操作符源码解析</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/jexo/2018/04/22/我是用来缓存的操作符-Cache/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count gitment-comments-count" data-xid="/jexo/2018/04/22/我是用来缓存的操作符-Cache/" itemprop="commentsCount"></span>
                </a>
              </span>
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h6 id="Cache操作符功能介绍"><a href="#Cache操作符功能介绍" class="headerlink" title="Cache操作符功能介绍"></a>Cache操作符功能介绍</h6><p>缓存前面操作通过<code>onNext</code>所传递下来的参数，在下一次<code>subscribe</code>订阅时，直接跳过前面的步骤，直接执行后面步骤。</p>
<h6 id="用途"><a href="#用途" class="headerlink" title="用途"></a>用途</h6><p>单纯用文字介绍Cache的功能，大家可能很难理解。大家可以想象下，比如http请求，我的前面操作是有延时的，如果没有用<code>cache</code>，每次<code>subscribe</code>都会去真正发起<code>http</code>请求。但是如果在尾部添加<code>cache</code>操作符的话，那么下一次<code>subscribe</code>的时候，其实就是直接从缓存中获取，而不会发起真正的<code>http</code>请求。</p>
<a id="more"></a>
<h6 id="来一段小代码"><a href="#来一段小代码" class="headerlink" title="来一段小代码"></a>来一段小代码</h6><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">  var handler = Handler()</span><br><span class="line">        <span class="comment">//延时后 cache的作用会更明显</span></span><br><span class="line"><span class="comment">//        observable = Observable.create(object : Observable.OnSubscribe&lt;String&gt; &#123;</span></span><br><span class="line"><span class="comment">//            override fun call(t: Subscriber&lt;in String&gt;) &#123;</span></span><br><span class="line"><span class="comment">//                t.onNext("Test1")</span></span><br><span class="line"><span class="comment">//                t.onNext("Test2")</span></span><br><span class="line"><span class="comment">//                t.onNext("Test3")</span></span><br><span class="line"><span class="comment">//            &#125;</span></span><br><span class="line"><span class="comment">//        &#125;).delay(4, TimeUnit.SECONDS).cache()</span></span><br><span class="line">        observable = Observable.create(object : Observable.OnSubscribe&lt;String&gt; &#123;</span><br><span class="line">            <span class="function">override fun <span class="title">call</span><span class="params">(t: Subscriber&lt;in String&gt;)</span> </span>&#123;</span><br><span class="line">                t.onNext(<span class="string">"Test1"</span>)</span><br><span class="line">                t.onNext(<span class="string">"Test2"</span>)</span><br><span class="line">                t.onNext(<span class="string">"Test3"</span>)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;).cache()</span><br><span class="line"></span><br><span class="line">        btSub.setOnClickListener(&#123;</span><br><span class="line">            observable?.subscribe(&#123; msg -&gt;</span><br><span class="line">                handler.post(Runnable &#123;</span><br><span class="line">                    tvContent.text = tvContent.text.toString() + <span class="string">"\n"</span> + msg</span><br><span class="line"></span><br><span class="line">                &#125;)</span><br><span class="line"></span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;)</span><br></pre></td></tr></table></figure>
<p>这里有一段注释的代码，是使用了<code>delay</code>，使用了<code>delay</code>之后<code>cache</code>的作用会更加明显，第一次点击按钮触发<code>subscribe</code>订阅后，会延迟4秒后，在界面上<code>Test1,Test2,Test3</code>，第二次，第三次…界面上都会立刻打印<code>Test1,Test2,Test3</code>，但是由于我还没有为大家介绍过<code>delay</code>操作符，所以我这里也先不过多介绍，在以后的文章中我们会为大家进行<code>delay</code>的源码分析。</p>
<h2 id="有了前面这么一大串的介绍后，我想大家对cache操作符有了一定的了解，那么我们就带着自己心中的疑问和猜想，按照demo的顺序一步步跟入源码。"><a href="#有了前面这么一大串的介绍后，我想大家对cache操作符有了一定的了解，那么我们就带着自己心中的疑问和猜想，按照demo的顺序一步步跟入源码。" class="headerlink" title="有了前面这么一大串的介绍后，我想大家对cache操作符有了一定的了解，那么我们就带着自己心中的疑问和猜想，按照demo的顺序一步步跟入源码。"></a>有了前面这么一大串的介绍后，我想大家对<code>cache</code>操作符有了一定的了解，那么我们就带着自己心中的疑问和猜想，按照demo的顺序一步步跟入源码。</h2><p>######看看源代码<br>Observable</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">final</span> Observable&lt;T&gt; <span class="title">cache</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> CachedObservable.from(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>CachedObservable</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> &lt;T&gt; <span class="function">CachedObservable&lt;T&gt; <span class="title">from</span><span class="params">(Observable&lt;? extends T&gt; source)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> (CachedObservable&lt;T&gt;)from(source, <span class="number">16</span>);</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> &lt;T&gt; <span class="function">CachedObservable&lt;T&gt; <span class="title">from</span><span class="params">(Observable&lt;? extends T&gt; source, <span class="keyword">int</span> capacityHint)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (capacityHint &lt; <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">"capacityHint &gt; 0 required"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        CacheState&lt;T&gt; state = <span class="keyword">new</span> CacheState&lt;T&gt;(source, capacityHint);</span><br><span class="line">        CachedSubscribe&lt;T&gt; onSubscribe = <span class="keyword">new</span> CachedSubscribe&lt;T&gt;(state);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> CachedObservable&lt;T&gt;(onSubscribe, state);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>个人理解：因为前面其实已经介绍到了，cache其实是把前面传递下来的参数，保存起来了，那么肯定是要有个数组或者列表的，这里我看到<code>capacityHint</code>，我就认为<code>CacheState</code>应该有可能是这个容器。<br>这倒不是最重要的，在<code>Observable</code>的子类中，其实我们最重要看的就是2个东西OnSubscribe,Subscriber明白了这2个东西，基本上对这个操作符就了解的差不多了</p>
</blockquote>
<p>CachedObservable.CacheState<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">CacheState</span>&lt;<span class="title">T</span>&gt; <span class="keyword">extends</span> <span class="title">LinkedArrayList</span> <span class="keyword">implements</span> <span class="title">Observer</span>&lt;<span class="title">T</span>&gt; </span>&#123;</span><br><span class="line">...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>CachedObservable.CachedSubscribe<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">CachedSubscribe</span>&lt;<span class="title">T</span>&gt; <span class="keyword">extends</span> <span class="title">AtomicBoolean</span> <span class="keyword">implements</span> <span class="title">OnSubscribe</span>&lt;<span class="title">T</span>&gt; </span>&#123;</span><br><span class="line">  ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>OnSubscribe很明显，就是<code>CachedSubscribe</code>。<br>那么<code>CacheState</code>是不是<code>Subscriber</code>？，在这里<code>CacheState</code>实现了<code>Observer</code>接口<br>Observer<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Observer</span>&lt;<span class="title">T</span>&gt; </span>&#123;    </span><br><span class="line">   <span class="function"><span class="keyword">void</span> <span class="title">onCompleted</span><span class="params">()</span></span>;  </span><br><span class="line">   <span class="function"><span class="keyword">void</span> <span class="title">onError</span><span class="params">(Throwable e)</span></span>;    </span><br><span class="line">   <span class="function"><span class="keyword">void</span> <span class="title">onNext</span><span class="params">(T t)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>前面我们几篇文章都介绍了，<code>Subscriber</code>其实就是<code>onNext..</code>等方法的具体实现。所以我们可以直接把<code>CacheState</code>当作是<code>Subscriber</code>来看待，这样会很好的帮助我们理解。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Subscriber</span>&lt;<span class="title">T</span>&gt; <span class="keyword">implements</span> <span class="title">Observer</span>&lt;<span class="title">T</span>&gt;, <span class="title">Subscription</span> </span>&#123;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>个人理解：Subscriber和Observer关系<br>Subscriber实现了Observer接口，Subscriber可以<code>subscribe</code>,<code>unsubscribe</code>，还有<code>onStart</code>方法。<br>在RxJava操作符中，其实我们关心的是<code>Subscrber</code>的<code>onNext</code>方法和<code>OnSubscribe</code>的<code>call</code>方法，能搞定这2个方法，那么我们就对这个操作符有了很深的了解了。</p>
</blockquote>
<p>既然我们已经找到了2个重要的对象，那么我们继续往下深入。<br>Observable.cache调用后得到了一个<code>CachedObservable</code>，然后点击按钮调用<code>subscribe</code><br>Observable<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> Subscription <span class="title">subscribe</span><span class="params">(<span class="keyword">final</span> Action1&lt;? <span class="keyword">super</span> T&gt; onNext)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (onNext == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">"onNext can not be null"</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        Action1&lt;Throwable&gt; onError = InternalObservableUtils.ERROR_NOT_IMPLEMENTED;</span><br><span class="line">        Action0 onCompleted = Actions.empty();</span><br><span class="line">        <span class="keyword">return</span> subscribe(<span class="keyword">new</span> ActionSubscriber&lt;T&gt;(onNext, onError, onCompleted));</span><br><span class="line">    &#125;</span><br><span class="line">...</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">final</span> Subscription <span class="title">subscribe</span><span class="params">(Subscriber&lt;? <span class="keyword">super</span> T&gt; subscriber)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> Observable.subscribe(subscriber, <span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line">...</span><br><span class="line"><span class="keyword">static</span> &lt;T&gt; <span class="function">Subscription <span class="title">subscribe</span><span class="params">(Subscriber&lt;? <span class="keyword">super</span> T&gt; subscriber, Observable&lt;T&gt; observable)</span> </span>&#123;</span><br><span class="line">...</span><br><span class="line">        subscriber.onStart();</span><br><span class="line">        <span class="keyword">if</span> (!(subscriber <span class="keyword">instanceof</span> SafeSubscriber)) &#123;</span><br><span class="line">            subscriber = <span class="keyword">new</span> SafeSubscriber&lt;T&gt;(subscriber);</span><br><span class="line">        &#125;</span><br><span class="line">            RxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber);</span><br><span class="line">           ...</span><br></pre></td></tr></table></figure></p>
<p>这里我贴出这块代码，其实在前面几篇文章我都贴过了，这里重新贴出希望大家加强记忆。调用<code>subscribe</code>方法，其实就是<code>obsevable.onSubscibe.call(subscriber)</code><br>关键的地方来了，这里的<code>obsevable,onSubscribe,subscriber</code>分别是什么呢？<br>链式结构中，操作符使用的越多，到最后会越难判断，这里我们只有一个操作符，相对来说比较简单<br>这里的<code>observable</code>很明显就是<code>CachedObservable</code>而<code>obsevable.onSubscibe</code>自然就是刚才我们分析得到的<code>CachedSubscribe</code>，如果你想当然的以为<code>subscriber</code>就是刚才的<code>CacheState</code>那就错了。<br>那么<code>subscriber</code>到底是什么呢？<br>我们从刚才的代码一步步往上推，其实就明白。<br><code>subscriber</code>是一个参数由外部传入的，<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"> <span class="keyword">if</span> (!(subscriber <span class="keyword">instanceof</span> SafeSubscriber)) &#123;</span><br><span class="line">            subscriber = <span class="keyword">new</span> SafeSubscriber&lt;T&gt;(subscriber);</span><br><span class="line">        &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure></p>
<p>其实已经告诉我们，最终的<code>subscriber</code>其实是一个<code>SafeSubscriber</code>。而原来的<code>subscriber</code>当作构造参数保存在了<code>SafeSubscriber</code>中。</p>
<p>再往前看，看原来的<code>subscriber</code>是什么。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">final</span> Subscription <span class="title">subscribe</span><span class="params">(<span class="keyword">final</span> Action1&lt;? <span class="keyword">super</span> T&gt; onNext)</span> </span>&#123;</span><br><span class="line">       ...</span><br><span class="line">        <span class="keyword">return</span> subscribe(<span class="keyword">new</span> ActionSubscriber&lt;T&gt;(onNext, onError, onCompleted));</span><br><span class="line">    &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure></p>
<p>很明显的就是，我们在demo中传入的<code>Action</code>被包装成了<code>ActionSubscriber</code>。</p>
<p><strong>看图说话</strong><br><img src="https://upload-images.jianshu.io/upload_images/4241874-570970126466b212.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<p>所以最终是这么一个<code>subscriber</code>。</p>
<p>那么我们继续深入。</p>
<p><code>observable.onSubscriber.call(subscriber)</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">CachedSubscribe</span>&lt;<span class="title">T</span>&gt; <span class="keyword">extends</span> <span class="title">AtomicBoolean</span> <span class="keyword">implements</span> <span class="title">OnSubscribe</span>&lt;<span class="title">T</span>&gt; </span>&#123;</span><br><span class="line"> ...</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">call</span><span class="params">(Subscriber&lt;? <span class="keyword">super</span> T&gt; t)</span> </span>&#123;</span><br><span class="line">            ReplayProducer&lt;T&gt; rp = <span class="keyword">new</span> ReplayProducer&lt;T&gt;(t, state);</span><br><span class="line">            state.addProducer(rp);</span><br><span class="line">            t.add(rp);</span><br><span class="line">            t.setProducer(rp);</span><br><span class="line">            <span class="keyword">if</span> (!get() &amp;&amp; compareAndSet(<span class="keyword">false</span>, <span class="keyword">true</span>)) &#123;</span><br><span class="line">                state.connect();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>我们一句一句来分析。</p>
<ol>
<li>创建<code>ReplayProducer</code>对象<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">   <span class="keyword">static</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">ReplayProducer</span>&lt;<span class="title">T</span>&gt; <span class="keyword">extends</span> <span class="title">AtomicLong</span> <span class="keyword">implements</span> <span class="title">Producer</span>, <span class="title">Subscription</span> </span>&#123;</span><br><span class="line">       ...</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="title">ReplayProducer</span><span class="params">(Subscriber&lt;? <span class="keyword">super</span> T&gt; child, CacheState&lt;T&gt; state)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">this</span>.child = child;</span><br><span class="line">            <span class="keyword">this</span>.state = state;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">request</span><span class="params">(<span class="keyword">long</span> n)</span> </span>&#123;</span><br><span class="line">        ...</span><br><span class="line">        &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p><code>ReplayProducer</code>是一个<code>Producer</code>，前面介绍过<code>Producer</code>，我们只需要看它<code>request</code>方法就好了。我们先等下看它的<code>request</code>。</p>
<ol start="2">
<li>把<code>ReplayProducer</code>添加到<code>CacheState</code>对象中<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addProducer</span><span class="params">(ReplayProducer&lt;T&gt; p)</span> </span>&#123;</span><br><span class="line">           <span class="keyword">synchronized</span> (connection) &#123;</span><br><span class="line">               ReplayProducer&lt;?&gt;[] a = producers;</span><br><span class="line">               <span class="keyword">int</span> n = a.length;</span><br><span class="line">               ReplayProducer&lt;?&gt;[] b = <span class="keyword">new</span> ReplayProducer&lt;?&gt;[n + <span class="number">1</span>];</span><br><span class="line">               System.arraycopy(a, <span class="number">0</span>, b, <span class="number">0</span>, n);</span><br><span class="line">               b[n] = p;</span><br><span class="line">               producers = b;</span><br><span class="line">           &#125;</span><br><span class="line">       &#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>这里用的是数组的形式，来添加一个新元素，比较简单，就不过多介绍了。</p>
<ol start="3">
<li>把<code>ReplyProducer</code>当作<code>Subscription</code>和<code>Subscriber</code>绑定在一起。<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title">add</span><span class="params">(Subscription s)</span> </span>&#123;</span><br><span class="line">        subscriptions.add(s);</span><br><span class="line">    &#125;</span><br><span class="line">...</span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title">unsubscribe</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        subscriptions.unsubscribe();</span><br><span class="line">    &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>可以理解为，当<code>subscriber.unsubscribe</code>，对应的<code>Producer</code>也取消了订阅。这种操作在前面几个操作符中也有出现。</p>
<ol start="4">
<li>调用<code>Producer</code>的<code>request</code>方法<br>setProducer的操作呢，我们在前面也介绍过，就是直接调用<code>Producer</code>的request方法</li>
</ol>
<blockquote>
<p>注意：由于我们现在只使用一个操作符，比较简单，先这么理解，后续我们讲多个操作符混合使用就可能会出现比较复杂的情况，由浅入深，慢慢理解。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">request</span><span class="params">(<span class="keyword">long</span> n)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">for</span> (;;) &#123;</span><br><span class="line">                <span class="keyword">long</span> r = get();</span><br><span class="line">                <span class="keyword">if</span> (r &lt; <span class="number">0</span>) &#123;</span><br><span class="line">                    <span class="keyword">return</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">long</span> u = r + n;</span><br><span class="line">                <span class="keyword">if</span> (u &lt; <span class="number">0</span>) &#123;</span><br><span class="line">                    u = Long.MAX_VALUE;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (compareAndSet(r, u)) &#123;</span><br><span class="line">                    replay();</span><br><span class="line">                    <span class="keyword">return</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">replay</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (<span class="keyword">this</span>) &#123;</span><br><span class="line">                <span class="keyword">if</span> (emitting) &#123;</span><br><span class="line">                    missed = <span class="keyword">true</span>;</span><br><span class="line">                    <span class="keyword">return</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                emitting = <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">boolean</span> skipFinal = <span class="keyword">false</span>;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="keyword">final</span> Subscriber&lt;? <span class="keyword">super</span> T&gt; child = <span class="keyword">this</span>.child;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">for</span> (;;) &#123;</span><br><span class="line"></span><br><span class="line">                    <span class="keyword">long</span> r = get();</span><br><span class="line"></span><br><span class="line">                    <span class="keyword">if</span> (r &lt; <span class="number">0L</span>) &#123;</span><br><span class="line">                        skipFinal = <span class="keyword">true</span>;</span><br><span class="line">                        <span class="keyword">return</span>;</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">int</span> s = state.size();</span><br><span class="line">                    <span class="keyword">if</span> (s != <span class="number">0</span>) &#123;</span><br><span class="line">                      <span class="comment">//这段代码当读提出来分析</span></span><br><span class="line">                        ...</span><br><span class="line"></span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">synchronized</span> (<span class="keyword">this</span>) &#123;</span><br><span class="line">                        <span class="keyword">if</span> (!missed) &#123;</span><br><span class="line">                            emitting = <span class="keyword">false</span>;</span><br><span class="line">                            skipFinal = <span class="keyword">true</span>;</span><br><span class="line">                            <span class="keyword">return</span>;</span><br><span class="line">                        &#125;</span><br><span class="line">                        missed = <span class="keyword">false</span>;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> (!skipFinal) &#123;</span><br><span class="line">                    <span class="keyword">synchronized</span> (<span class="keyword">this</span>) &#123;</span><br><span class="line">                        emitting = <span class="keyword">false</span>;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>
<p><code>request</code>方法中呢，其实主要调用了<code>replay</code>方法。<br>里面最重要的一句是<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> s = state.size();</span><br><span class="line"><span class="keyword">if</span> (s != <span class="number">0</span>) &#123;</span><br><span class="line">...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>由于第一次调用<code>subscribe</code>所以根本没有缓存东西，所以<code>state.size()==0</code>，所以第一调用<code>replay</code>方法基本上没有做什么操作。</p>
<ol start="5">
<li>第一次调用<code>subscribe</code>执行<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (!get() &amp;&amp; compareAndSet(<span class="keyword">false</span>, <span class="keyword">true</span>)) &#123;</span><br><span class="line">               state.connect();</span><br><span class="line">           &#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>我们先来看<br><code>!get() &amp;&amp; compareAndSet(false, true)</code>，由于<code>CachedSubscribe&lt;T&gt; extends AtomicBoolean</code></p>
<p>第一次进来<code>get()==false</code>，然后再设置为<code>true</code>，确保了下一次不调用<code>state.connect</code></p>
<p>下面我们具体分析下connect方法，最重要的缓存操作在这里<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">connect</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            Subscriber&lt;T&gt; subscriber = <span class="keyword">new</span> Subscriber&lt;T&gt;() &#123;</span><br><span class="line">                <span class="meta">@Override</span></span><br><span class="line">                <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onNext</span><span class="params">(T t)</span> </span>&#123;</span><br><span class="line">                    CacheState.<span class="keyword">this</span>.onNext(t);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="meta">@Override</span></span><br><span class="line">                <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onError</span><span class="params">(Throwable e)</span> </span>&#123;</span><br><span class="line">                    CacheState.<span class="keyword">this</span>.onError(e);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="meta">@Override</span></span><br><span class="line">                <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCompleted</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                    CacheState.<span class="keyword">this</span>.onCompleted();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;;</span><br><span class="line">            connection.set(subscriber);</span><br><span class="line">            source.unsafeSubscribe(subscriber);</span><br><span class="line">            isConnected = <span class="keyword">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure></p>
<p>这里呢，我们还是分步骤一步步来解析</p>
<ol>
<li>创建一个<code>Subscriber</code><br>因为在前面，其实我们本身对<code>cache</code>的功能已经有所了解，就是在第一次以后，再调用<code>subscribe</code>其实就是直接把缓存数据拿过来直接传递下去。</li>
</ol>
<p>那么在这里，其实我们就可以看出，这里新建的<code>Subscriber</code>就是用来直接传递下去的<code>Subscriber</code>。这里其实我们可以画个大致的示意图。</p>
<p><strong>看图说话</strong><br><img src="https://upload-images.jianshu.io/upload_images/4241874-8d749caf6082f056.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<p>第一次<code>subscribe</code>走上面实现，第二次<code>subscribe</code>直接走下面虚线，而中间的这个<code>Subscriber</code>就是我们现在所提到的这个<code>Subscriber</code>。第二次以后就直接越过了demo中的<code>OnSubscribe</code>。</p>
<blockquote>
<p>注意: 这里没有涉及到demo中的<code>Subscriber</code>，通过前面的分析我们知道demo中的<code>Subscriber</code>已经被包装成了<code>SafeSubscriber</code>保存在<code>ReplyProducer</code>中的<code>child</code>变量里</p>
</blockquote>
<ol start="2">
<li>保存<code>subscriber</code><br>既然前面提到了，第一次之后的每次操作都会使用到这个<code>subscriber</code>，那么我们肯定要把这个<code>subscriber</code>保存起来。<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">set</span><span class="params">(Subscription s)</span> </span>&#123;</span><br><span class="line">     ...</span><br><span class="line">       state.update(s);</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>SequentialSubscription<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">update</span><span class="params">(Subscription next)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (;;) &#123;</span><br><span class="line">            Subscription current = get();</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (current == Unsubscribed.INSTANCE) &#123;</span><br><span class="line">                <span class="keyword">if</span> (next != <span class="keyword">null</span>) &#123;</span><br><span class="line">                    next.unsubscribe();</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (compareAndSet(current, next)) &#123;</span><br><span class="line">                <span class="keyword">if</span> (current != <span class="keyword">null</span>) &#123;</span><br><span class="line">                    current.unsubscribe();</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure></p>
<p>如我们所料，确实是把这个<code>subscriber</code>保存起来了。<br><code>compareAndSet(current, next)</code>。</p>
<ol start="3">
<li>第一次<code>subscribe</code>，还是要调用前面的<code>onSubscribe</code>的<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source.unsafeSubscribe(subscriber);</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>其实就是<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source.onSubscribe.call(subscriber);</span><br></pre></td></tr></table></figure></p>
<p>source我们可以通过源码知道，就是创建<code>CachedObservable</code>时传入的我们<code>demo</code>中<code>Observable.create()</code>得到的<code>Observable</code>对象。<br>onSubscribe就是<code>demo</code>中的<code>OnSubscribe</code>。<br>下面我们还是重点，放在<code>subscriber</code>上。</p>
<p>这里的<code>subscriber</code>其实我们根据上面的代码很容易判断出就是刚刚new 出来的<code>Subscriber</code>，并且在<code>onNext</code>其实是直接调用<code>CacheState</code>的<code>onNext</code>。</p>
<p>CachedObservable.CacheState<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onNext</span><span class="params">(T t)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">if</span> (!sourceDone) &#123;</span><br><span class="line">                Object o = NotificationLite.next(t);</span><br><span class="line">                add(o);</span><br><span class="line">                dispatch();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure></p>
<p>当我们在demo中<code>OnSubscribe</code>调用一次<code>subscriber.onNext</code>,其实就是进入<code>CachedObservable.CacheState</code>的<code>onNext</code>。</p>
<p>在这里我们再次一句一句分析。</p>
<ol>
<li>NotificationLite.next(t)</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> &lt;T&gt; <span class="function">Object <span class="title">next</span><span class="params">(T t)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (t == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> ON_NEXT_NULL_SENTINEL;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> t;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>很明显就是判断参数是否为null。</p>
<ol start="2">
<li>add(o)</li>
</ol>
<p>前面我们就提到了<code>CacheState</code>用来保存上面传递下来的参数.<br>具体实现就是在这里，add(o)。</p>
<ol start="3">
<li>dispatch()</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">dispatch</span><span class="params">()</span> </span>&#123;</span><br><span class="line">           ReplayProducer&lt;?&gt;[] a = producers;</span><br><span class="line">           <span class="keyword">for</span> (ReplayProducer&lt;?&gt; rp : a) &#123;</span><br><span class="line">               rp.replay();</span><br><span class="line">           &#125;</span><br><span class="line">       &#125;</span><br></pre></td></tr></table></figure>
<p>很明显这里最重要的就是<code>rp.replay()</code><br>我们先不管为什么这里为什么用了个for循环，我们先来看看<code>rp.replay</code>到底做了什么。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">replay</span><span class="params">()</span> </span>&#123;</span><br><span class="line">...</span><br><span class="line">  <span class="keyword">int</span> s = state.size();</span><br><span class="line">  <span class="keyword">if</span> (s != <span class="number">0</span>) &#123;</span><br><span class="line">      ...</span><br><span class="line">    <span class="keyword">if</span> (NotificationLite.accept(child, o)) &#123;</span><br><span class="line">      ...</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>NotificationLite.accept<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> &lt;T&gt; <span class="function"><span class="keyword">boolean</span> <span class="title">accept</span><span class="params">(Observer&lt;? <span class="keyword">super</span> T&gt; o, Object n)</span> </span>&#123;</span><br><span class="line">         ...</span><br><span class="line">            o.onNext((T) n);</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">         ...</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></p>
<p>reply就是判断<code>CacheState</code>的缓存是否已经有了，有了之后就直接调用<code>child.onNext(o)</code></p>
<p>那么<code>child</code>是什么呢？就是前面所分析的</p>
<p><img src="https://upload-images.jianshu.io/upload_images/4241874-570970126466b212.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<p>这样在一层一层的调用<code>onNext</code>最终到了我们自己的<code>Action</code>。</p>
<h6 id="第二次调用subscribe"><a href="#第二次调用subscribe" class="headerlink" title="第二次调用subscribe"></a>第二次调用<code>subscribe</code></h6><p>第一次调用<code>subscribe</code>的整个流程其实我们已经走完，下面我们直接简单的走一下第二次调用<code>subscribe</code>的流程。</p>
<p>直接从<code>CachedSubscribe</code>的<code>call</code>方法看起。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">call</span><span class="params">(Subscriber&lt;? <span class="keyword">super</span> T&gt; t)</span> </span>&#123;</span><br><span class="line">           ReplayProducer&lt;T&gt; rp = <span class="keyword">new</span> ReplayProducer&lt;T&gt;(t, state);</span><br><span class="line">           state.addProducer(rp);</span><br><span class="line">           t.add(rp);</span><br><span class="line">           t.setProducer(rp);</span><br><span class="line">           <span class="keyword">if</span> (!get() &amp;&amp; compareAndSet(<span class="keyword">false</span>, <span class="keyword">true</span>)) &#123;</span><br><span class="line">               state.connect();</span><br><span class="line">           &#125;</span><br><span class="line">       &#125;</span><br></pre></td></tr></table></figure></p>
<ol>
<li>又创建了一个<code>ReplayProducer</code></li>
<li>添加到<code>CacheState</code>中</li>
<li>把<code>ReplayProducer</code>加入到<code>SafeSubscriber</code>中绑定在一起</li>
<li>调用<code>Producer</code>的<code>request</code>方法，在这里其实就是调用<code>ReplayProducer</code>的<code>replay</code>方法(前面分析过了)</li>
<li>因为第一次的时候，已经设置为<code>true</code>所以<code>get()==true</code>直接跳过</li>
</ol>
<p>所以综上分析，我们还是直接看<code>ReplayProducer</code> 的<code>replay</code>方法。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">replay</span><span class="params">()</span> </span>&#123;</span><br><span class="line">...</span><br><span class="line">  <span class="keyword">int</span> s = state.size();</span><br><span class="line">  <span class="keyword">if</span> (s != <span class="number">0</span>) &#123;</span><br><span class="line">      ...</span><br><span class="line">    <span class="keyword">if</span> (NotificationLite.accept(child, o)) &#123;</span><br><span class="line">      ...</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>NotificationLite.accept<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> &lt;T&gt; <span class="function"><span class="keyword">boolean</span> <span class="title">accept</span><span class="params">(Observer&lt;? <span class="keyword">super</span> T&gt; o, Object n)</span> </span>&#123;</span><br><span class="line">         ...</span><br><span class="line">            o.onNext((T) n);</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">         ...</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></p>
<p>因为在第一次中我们已经在<code>CacheState</code>中保存了所有发射的对象。以我们当前的<code>demo</code>来看，<code>state</code>中保存了<code>Test1,Test2,Test3</code>3个字符串，然后就直接调用<code>SafeSubsciber</code>的onNext方法。</p>
<h6 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h6><p>总的来说，<code>cache</code>操作符与前2个操作符比较起来的话，在源码上其实看起来会更有难度，但是有了前2个操作符做铺垫，再来看，相对来说会比较容易。</p>
<h6 id="附加"><a href="#附加" class="headerlink" title="附加"></a>附加</h6><p>整体<code>cache</code>的流程，其实我们已经有了大致的了解，但是刚才其实我们还是遗留了一个问题。我们再次来看这段代码。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">dispatch</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            ReplayProducer&lt;?&gt;[] a = producers;</span><br><span class="line">            <span class="keyword">for</span> (ReplayProducer&lt;?&gt; rp : a) &#123;</span><br><span class="line">                rp.replay();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br></pre></td></tr></table></figure></p>
<p>这里为什么要用了一个<code>for</code>循环呢？</p>
<p>  <img src="https://upload-images.jianshu.io/upload_images/4241874-67860a5e18e7f6c7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<p>其实我们从上面的图片中可以看出。重复输出了3次<code>Test1,Test2,Test3</code>。<br>因为，我在demo中连续点击了3下<code>SUBSCRIBE</code>按钮。<br>也就是调用了3次<code>subscribe</code>，也就是往<code>CacheState</code>中添加了<br>3个<code>ReplayProducer</code>，所以上面调用<code>dispatch</code>方法的时候，自然就for循环调用了3次<code>replay</code>，然后就输出了3次。</p>
<hr>
<h5 id="大家喜欢的话就点个赞哦，给我点鼓励嘛"><a href="#大家喜欢的话就点个赞哦，给我点鼓励嘛" class="headerlink" title="大家喜欢的话就点个赞哦，给我点鼓励嘛"></a>大家喜欢的话就点个赞哦，给我点鼓励嘛</h5>
      
    </div>
    
    
    

    

    
      <div>
        <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
  <div>Donate comment here</div>
  <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
    <span>打赏</span>
  </button>
  <div id="QR" style="display: none;">

    
      <div id="wechat" style="display: inline-block">
        <img id="wechat_qr" src="/jexo/images/wechatpay.png" alt="Ling Hu 微信支付"/>
        <p>微信支付</p>
      </div>
    

    
      <div id="alipay" style="display: inline-block">
        <img id="alipay_qr" src="/jexo/images/alipay.png" alt="Ling Hu 支付宝"/>
        <p>支付宝</p>
      </div>
    

    

  </div>
</div>

      </div>
    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/jexo/tags/Android/" rel="tag"># Android</a>
          
            <a href="/jexo/tags/RxJava/" rel="tag"># RxJava</a>
          
            <a href="/jexo/tags/源码解析/" rel="tag"># 源码解析</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/jexo/2018/04/18/我是用来组合的操作符-Buffer/" rel="next" title="我是用来组合的操作符------Buffer">
                <i class="fa fa-chevron-left"></i> 我是用来组合的操作符------Buffer
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  
    <div class="comments" id="comments">
      
        <div id="gitment-container"></div>
      
    </div>

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image"
                src="/jexo/images/avatar.jpg"
                alt="Ling Hu" />
            
              <p class="site-author-name" itemprop="name">Ling Hu</p>
              <p class="site-description motion-element" itemprop="description">Android,源码解析,每天进步一点点</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/jexo/archives/">
              
                  <span class="site-state-item-count">19</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/jexo/categories/index.html">
                  <span class="site-state-item-count">9</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/jexo/tags/index.html">
                  <span class="site-state-item-count">14</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://github.com/javalong" target="_blank" title="GitHub">
                      
                        <i class="fa fa-fw fa-github"></i>GitHub</a>
                  </span>
                
            </div>
          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-6"><a class="nav-link" href="#Cache操作符功能介绍"><span class="nav-number">1.</span> <span class="nav-text">Cache操作符功能介绍</span></a></li><li class="nav-item nav-level-6"><a class="nav-link" href="#用途"><span class="nav-number">2.</span> <span class="nav-text">用途</span></a></li><li class="nav-item nav-level-6"><a class="nav-link" href="#来一段小代码"><span class="nav-number">3.</span> <span class="nav-text">来一段小代码</span></a></li></ol></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#有了前面这么一大串的介绍后，我想大家对cache操作符有了一定的了解，那么我们就带着自己心中的疑问和猜想，按照demo的顺序一步步跟入源码。"><span class="nav-number"></span> <span class="nav-text">有了前面这么一大串的介绍后，我想大家对cache操作符有了一定的了解，那么我们就带着自己心中的疑问和猜想，按照demo的顺序一步步跟入源码。</span></a><ol class="nav-child"><li class="nav-item nav-level-6"><a class="nav-link" href="#第二次调用subscribe"><span class="nav-number">1.</span> <span class="nav-text">第二次调用subscribe</span></a></li><li class="nav-item nav-level-6"><a class="nav-link" href="#总结"><span class="nav-number">2.</span> <span class="nav-text">总结</span></a></li><li class="nav-item nav-level-6"><a class="nav-link" href="#附加"><span class="nav-number">3.</span> <span class="nav-text">附加</span></a></li></ol></li><li class="nav-item nav-level-5"><a class="nav-link" href="#大家喜欢的话就点个赞哦，给我点鼓励嘛"><span class="nav-number"></span> <span class="nav-text">大家喜欢的话就点个赞哦，给我点鼓励嘛</span></a></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2018</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Ling Hu</span>

  
</div>









        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/jexo/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/jexo/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/jexo/js/src/motion.js?v=5.1.4"></script>



  
  

  
  <script type="text/javascript" src="/jexo/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/jexo/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/jexo/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  







<!-- LOCAL: You can save these files to your site and update links -->
    
        
        <link rel="stylesheet" href="https://aimingoo.github.io/gitmint/style/default.css">
        <script src="https://aimingoo.github.io/gitmint/dist/gitmint.browser.js"></script>
    
<!-- END LOCAL -->

    
      <style>
        a.gitment-editor-footer-tip { display: none; }
        .gitment-container.gitment-footer-container { display: none; }
      </style>
    

    
      <script type="text/javascript">
      function renderGitment(){
        var gitment = new Gitmint({
            id: getId(),
            owner: 'javalong',
            repo: 'RxJava-Operator',
            
            lang: "zh-Hans" || navigator.language || navigator.systemLanguage || navigator.userLanguage,
            
            oauth: {
            
            
                client_secret: '06b042e57b8420f5002a6407348dde078bcde761',
            
                client_id: '1b5481d6512b2f28d7a2'
            }});
        gitment.render('gitment-container');
      }

      function getId(){
            if( window.location.pathname.length>=50){
                return window.location.pathname.substr(0,50)
            }else{
                return window.location.pathname
            }
      }

      
      renderGitment();
      
      </script>
    







  





  

  

  

  
  

  

  

  

</body>
</html>
